/*
 * kdtree_viewer.cpp
 *
 *  Created on: May 1, 2011
 *      Author: tqlong
 */

#include <QtGui/QPen>
#include "../common/common.h"
#include "kdtree_viewer.h"
#include <stack>

KDTreeViewer::KDTreeViewer(const std::string& inName,
    const std::string& outName, const std::string& format) :
  m_inName(inName), m_outName(outName), m_format(format), m_data(NULL), m_tree(
      NULL)
{
  reload();
}

void
KDTreeViewer::plot(Plotter& pl)
{
  QPen pen(Qt::SolidLine);
  pen.setWidth(2);
  pen.setColor(Qt::blue);
  common::drawDSet<dataset_type>(*m_data, pl, pen);
  //  for (int i=0; i<m_data->n(); i++)
  //    pl.drawText(pl.point(m_data->get(i)), QString::number(i));

  pen.setWidth(1);
  pen.setColor(Qt::red);
  pen.setStyle(Qt::DashLine);
  pl.setPen(pen);

  std::stack<tree_type*> s;
  s.push(m_tree);
  while (!s.empty())
    {
      tree_type* node = s.top();
      s.pop();
      const tree_type::box_type& b = node->box();
      pl.drawRect(QRectF(pl.point(b.min()), pl.point(b.max())));
      for (int i = 0; i < node->n_child(); i++)
        s.push(node->child(i));
    }

}

void
KDTreeViewer::reload()
{
  if (m_data)
    delete m_data;
  if (m_tree)
    delete m_tree;

  m_data = new dataset_type(m_inName, m_format);
  m_data->reload();
  m_tree = new tree_type(*m_data);
  m_tree->load(m_outName);
}

KNNViewer::KNNViewer(const std::string& inName, const std::string& qName,
    const std::string& outName, const std::string& format, bool number) :
  m_inName(inName), m_outName(outName), m_qName(qName), m_format(format), m_number(number),
      m_inData(inName, format, true), m_qData(qName, format, true)
{
  reload();
}

void
KNNViewer::plot(Plotter& pl)
{
  QPen pen(Qt::SolidLine);
  pen.setWidth(2);
  pen.setColor(Qt::blue);
  common::drawDSet<dataset_type>(m_inData, pl, pen, m_number);

  pen.setColor(Qt::red);
  common::drawDSet<dataset_type>(m_qData, pl, pen, m_number);

  pen.setStyle(Qt::DashLine);
  pen.setWidth(1);
  pen.setColor(Qt::black);
  pl.setPen(pen);
  for (unsigned int i = 0; i < m_nnIdx.size(); i++)
    {
      const vec_type& q = m_qData.get(i);
      for (unsigned int j = 0; j < m_nnIdx[i].size(); j++)
        {
          const vec_type& r = m_inData.get(m_nnIdx[i][j]);
          pl.drawLine(pl.point(q), pl.point(r));
        }
    }
}

void
KNNViewer::reload()
{
  m_inData.reload();
  m_qData.reload();
  m_nnIdx.clear();
  std::ifstream is(m_outName.c_str());
  while (!is.eof())
    {
      std::string line;
      std::getline(is, line);
      if (line.empty())
        continue;
      std::stringstream ss(line);
      int nn;
      ss >> nn;
      m_nnIdx.push_back(vint_type());
      vint_type& v = m_nnIdx.back();
      //    Log::m_log << nn;
      for (int i = 0; i < nn; i++)
        {
          int idx;
          ss >> idx;
          v.push_back(idx);
          //      Log::m_log << " " << idx;
        }
      //    Log::m_log << endl;
    }
  is.close();
}
